﻿using CodeGenerator.DBInfo.entity;
using RazorEngine.Templating;
using RazorEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using CodeGenerator.DBInfo;
using System.Text.RegularExpressions;
using System.Net;
namespace CodeGenerator.Utils
{
    /// <summary>
    /// 代码模板生成器
    /// </summary>
    internal class TemplateGenerator
    {
        /// <summary>
        /// 生成后端代码
        /// </summary>
        /// <param name="tableInfo">表信息</param>
        /// <param name="basePkgName">java基础包名</param>
        /// <param name="templateRootPath">模板文件夹路径</param>
        /// <param name="templatePathInfos">模板路径</param>
        /// <param name="outputDir">输出文件夹</param
        /// <param name="extraVars">额外变量</param>
        public static void GenerateBackCode(IDBInfoGetter dbInfoGetter, string moduleName, TableInfo tableInfo, string basePkgName, string templateRootPath, string[] templatePathInfos, string outputDir, Dictionary<string, dynamic> extraVars)
        {
            moduleName = moduleName.IsNullOrEmpty() ? "" : moduleName;
            var templatePath = $"{templatePathInfos[0]}\\{templatePathInfos[2]}";
            templatePath = Regex.Replace(templatePath, @"\\+", "\\");
            var outputNameTpl = templatePathInfos[3];
            //模板内容
            var templateContent = File.ReadAllText(templatePath);
            var relativePath = $"{templatePathInfos[1]}\\{templatePathInfos[2]}".Replace("/", "\\");
            relativePath = relativePath.Replace("{moduleName}", moduleName);
            relativePath = Regex.Replace(relativePath, @"\\+", "\\");
            #region 获取包名
            var subPkgPath = "";
            var substr = "{basePkg}\\";
            // 找到第一个斜杠的位置
            int firstSlashIndex = relativePath.IndexOf(substr);

            // 找到最后一个斜杠的位置
            int lastSlashIndex = relativePath.LastIndexOf('\\');

            // 检查是否找到了斜杠
            if (firstSlashIndex == -1 || lastSlashIndex == -1 || firstSlashIndex == lastSlashIndex)
            {
                subPkgPath = string.Empty.ToLower(); // 如果路径中没有斜杠或者只有一个斜杠，则返回空字符串
            }
            else
            {
                // 提取第一个斜杠和最后一个斜杠之间的内容
                subPkgPath = relativePath.Substring(firstSlashIndex + substr.Length, lastSlashIndex - firstSlashIndex - substr.Length).ToLower();
            }
            var pkgName = basePkgName;
            if (subPkgPath.IsNotNullAndNotEmpty())
            {
                pkgName = basePkgName + "." + subPkgPath.Replace("\\", ".");
                if (!pkgName.IsJavaPackageName())
                {
                    throw new Exception($"{pkgName} 不是合法Java包名，请修改模板路径，不要包含特殊符号");
                }
            }
            #endregion
            var projectName = basePkgName.Split('.').Last();
            //模板变量
            var model = new
            {
                TableInfo = tableInfo,
                BasePkgName = basePkgName,
                ModuleName = moduleName,
                DBInfoGetter = dbInfoGetter,
                ExtraVars = extraVars
            };
            //如果每次key都一样好像不会生成，所以用当前时间作为key
            var timeTicks = DateTime.Now.Ticks.ToString();
            //渲染结果
            var result = Engine.Razor.RunCompile(templateContent, timeTicks, null, model);
            #region 修改文件名
            var smallTableName = tableInfo.TrimPrefixName.ToSmallCamelCase();
            var tableName = tableInfo.TrimPrefixName.ToBigCamelCase();
            //模板可能在多级文件夹内，先拼接再修改文件名，写入生成路径并修改文件名
            var relativePathReplace = relativePath.Replace("{basePkg}", basePkgName.Replace(".", "\\"))
                .Replace("{tableName}", tableName)
                .Replace("{smallTableName}", smallTableName)
                .Replace("{projectName}", projectName);
            var outputPath = $"{outputDir}\\{relativePathReplace}";
            string directoryPath = Path.GetDirectoryName(outputPath);
            // 构建新的文件路径,文件名为表名转大驼峰
            outputPath = Path.Combine(directoryPath, outputNameTpl.Replace("{tableName}", tableName).Replace("{smallTableName}", smallTableName));
            // 如果目录不存在，创建目录
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            #endregion

            //写入文件
            File.WriteAllText(outputPath, WebUtility.HtmlDecode(result));
        }
        /// <summary>
        /// 生成前端代码
        /// </summary>
        /// <param name="tableInfo">表信息</param>
        /// <param name="templateRootPath">模板文件夹路径</param>
        /// <param name="templatePathInfos">模板路径</param>
        /// <param name="outputDir">输出文件夹</param
        /// <param name="extraVars">额外变量</param>
        public static void GenerateFrontCode(IDBInfoGetter dbInfoGetter, string moduleName, TableInfo tableInfo, string templateRootPath, string[] templatePathInfos, string outputDir, Dictionary<string, dynamic> extraVars)
        {
            moduleName = moduleName.IsNullOrEmpty() ? "" : moduleName;
            var templatePath = $"{templatePathInfos[0]}\\{templatePathInfos[2]}";
            templatePath = Regex.Replace(templatePath, @"\\+", "\\");
            var outputNameTpl = templatePathInfos[3];
            //模板内容
            var templateContent = File.ReadAllText(templatePath);
            var relativePath = $"{templatePathInfos[1]}\\{templatePathInfos[2]}".Replace("/", "\\");
            relativePath = relativePath.Replace("{moduleName}", moduleName);
            relativePath = Regex.Replace(relativePath, @"\\+", "\\");
            //模板变量
            var model = new
            {
                TableInfo = tableInfo,
                ModuleName= moduleName,
                DBInfoGetter = dbInfoGetter,
                ExtraVars = extraVars
            };
            //如果每次key都一样好像不会生成，所以用当前时间作为key
            var timeTicks = DateTime.Now.Ticks.ToString();
            //渲染结果
            var result = Engine.Razor.RunCompile(templateContent, timeTicks, null, model);
            #region 修改文件名
            var smallTableName = tableInfo.TrimPrefixName.ToSmallCamelCase();
            var tableName = tableInfo.TrimPrefixName.ToBigCamelCase();
            //模板可能在多级文件夹内，先拼接再修改文件名，写入生成路径并修改文件名
            var relativePathReplace = relativePath.Replace("{tableName}", tableName)
                .Replace("{smallTableName}", smallTableName);
            var outputPath = $"{outputDir}\\{relativePathReplace}";
            string directoryPath = Path.GetDirectoryName(outputPath);
            // 构建新的文件路径,文件名为表名转大驼峰
            outputPath = Path.Combine(directoryPath, outputNameTpl.Replace("{tableName}", tableName).Replace("{smallTableName}", smallTableName));
            // 如果目录不存在，创建目录
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            #endregion
            //写入文件
            File.WriteAllText(outputPath, WebUtility.HtmlDecode(result));
        }
    }
}
